<?PHP
	class User extends DBObject
	{
		function __construct($id = "")
		{
			parent::__construct('users', 'user_id', array('username', 'password', 'level', 'email'), $id);
		}
	}

	class Feedback extends DBObject
	{
		function __construct($id = "")
		{
			parent::__construct('feedback', 'id', array('appname', 'appversion', 'systemversion', 'email', 'reply', 'type', 'message', 'importance', 'critical', 'dt', 'ip', 'new', 'starred'), $id);
		}
		
		static function newCountTotal()
		{
			global $db;
			return $db->getValue("SELECT COUNT(*) FROM feedback WHERE new = '1'");
		}
	}

	class App extends DBObject
	{
		function __construct($id = "")
		{
			parent::__construct('apps', 'id', array('name', 'link', 'description', 'use_md5', 'upload_type', 's3key', 's3pkey', 's3bucket', 's3path', 'ap_key', 'ap_pkey', 'download_url', 'ap_email', 'ap_subject', 'ap_body', 'ap_license_ext', 'ap_bcc', 'sparkle_name'), $id);
		}
		
		function delete()
		{
			global $db;
			$db->query("DELETE FROM versions WHERE app_id = '{$this->id}'");
			parent::delete();
		}
		
		function currentVersion()
		{
			global $db;
			$ret = $db->getValue("SELECT version FROM versions WHERE app_id = '{$this->id}' ORDER BY dt DESC LIMIT 1");
			return ($ret === false) ? "None" : $ret;
		}

		function lastRelease()
		{
			global $db;
			$ret = $db->getValue("SELECT dt FROM versions WHERE app_id = '{$this->id}' ORDER BY dt DESC LIMIT 1");
			return ($ret === false) ? "None" : $ret;
		}
		
		function numQuestions()
		{
			global $db;
			$name = $db->quote($this->sparkle_name);
			return $db->getValue("SELECT COUNT(*) FROM feedback WHERE appname = $name AND type = 'support' AND new = 1");
		}
		
		function numBugs()
		{
			global $db;
			$name = $db->quote($this->sparkle_name);
			return $db->getValue("SELECT COUNT(*) FROM feedback WHERE appname = $name AND type = 'bug' AND new = 1");
		}
		
		function numFeatures()
		{
			global $db;
			$name = $db->quote($this->sparkle_name);
			return $db->getValue("SELECT COUNT(*) FROM feedback WHERE appname = $name AND type = 'feature' AND new = 1");
		}
		
		function feed()
		{
			global $db;
			$feed = new RSS();
			$feed->title       = $this->name;
			$feed->link        = $this->link;
			$feed->description = $this->description;

			$v = new Version();
			$versions = $v->glob("WHERE app_id = '{$this->id}' ORDER BY dt DESC LIMIT 10");
			foreach($versions as $v)
			{
				$item = new RSSItem();
				$item->title = $v->title;
				$item->link  = $v->downloadLink();
				$item->setPubDate($v->dt); 
				$item->description = $v->changes;

				if($this->use_md5)
					$item->enclosure($item->link, "application/octet-stream", $v->length, $v->md5);
				else
					$item->enclosure($item->link, "application/octet-stream", $v->length);

				$feed->addItem($item);
			}

			return $feed->out();
		}

		function getBody($order)
		{
			return str_replace(array('{first_name}', '{last_name}'), array($order->first_name, $order->last_name), $this->ap_body);
		}
		
		function newFeedbackCount()
		{
			global $db;
			return $db->getValue("SELECT COUNT(*) FROM feedback WHERE app_id = '{$this->id}' AND new = '1'");
		}
	}


	class Version extends DBObject
	{
		function __construct($id = "")
		{
			parent::__construct('versions', 'id', array('title', 'app_id', 'version', 'changes', 'dt', 'length', 'md5', 'ext'), $id);
		}
		
		function downloadLink()
		{
			$app = new App($this->app_id);
			if($app->upload_type == "s3")
				return slash($app->s3path) . strtolower(preg_replace('/[^a-zA-Z0-9]/', '', $app->name)) . "_" . $this->version . "." . $this->ext;
			else // TODO: This obviously need to be configurable
				return WEB_ROOT . "uploads/" . strtolower(preg_replace('/[^a-zA-Z0-9]/', '', $app->name)) . "_" . $this->version . "." . $this->ext;
		}
	}

	class Sparkle extends DBObject
	{
		function __construct($id = "")
		{
			parent::__construct('sparkle', 'osVersion', array('cputype', 'cpusubtype', 'model', 'ncpu', 'lang', 'appName', 'appVersion', 'cpuFreqMHz', 'ramMB', 'ip', 'dt'), $id);
		}
	}
	
	class Order extends DBObject
	{
		function __construct($id = "")
		{
			parent::__construct('orders', 'id', array('app_id', 'dt', 'txn_type', 'first_name', 'last_name', 'residence_country', 'item_name', 'payment_gross', 'mc_currency', 'business', 'payment_type', 'verify_sign', 'payer_status', 'tax', 'payer_email', 'txn_id', 'quantity', 'receiver_email', 'payer_id', 'receiver_id', 'item_number', 'payment_status', 'payment_fee', 'mc_fee', 'shipping', 'mc_gross', 'custom', 'license', 'type', 'deleted'), $id);
		}
		
		function generateLicense()
		{
			// Much of the following code is adapted/copied from AquaticPrime's PHP library...
			
			// Create our license dictionary to be signed
			$dict = array("Product"       => $this->item_name,
						  "Name"          => $this->first_name . ' ' . $this->last_name,
						  "Email"         => $this->payer_email,
						  "Licenses"      => $this->quantity,
						  "Timestamp"     => date('r', strtotime($this->dt)),
						  "TransactionID" => $this->txn_id);
			$app = new App($this->app_id);
		    $sig = chunk_split(getSignature($dict, $app->ap_key, $app->ap_pkey));

		    $plist = "<?xml version=\"1.0\" encoding=\"UTF-8\"?".">\n";
		    $plist .= "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n";
		    $plist .= "<plist version=\"1.0\">\n<dict>\n";
		    foreach($dict as $key => $value)
			{
		        $plist .= "\t<key>" . htmlspecialchars($key, ENT_NOQUOTES) . "</key>\n";
		        $plist .= "\t<string>" . htmlspecialchars($value, ENT_NOQUOTES) . "</string>\n";
		    }
		    $plist .= "\t<key>Signature</key>\n";
		    $plist .= "\t<data>$sig</data>\n";
		    $plist .= "</dict>\n";
		    $plist .= "</plist>\n";

			$this->license = $plist;
			$this->update();
		}
		
		function licenseFilename()
		{
			$app = new App($this->app_id);
			if($app->id = "") return false;

			$fn = ucwords($this->first_name) . '_' . ucwords($this->last_name) . '.' . $app->ap_license_ext;
			// $fn = preg_replace('/[^a-zA-Z0-9_-]/', '', $fn); // This will break international characters
			$fn = str_replace(' ', '', $fn);
			return $fn;
		}
		
		function emailLicense()
		{
			$app = new App($this->app_id);
			if($app->id = "") return false;

			send_mail_with_attachment($this->payer_email, $app->ap_email, $app->ap_subject, $app->getBody($this), $this->license, $this->licenseFilename(), $app->ap_bcc);
			return true;
		}
		
		function keys()
		{
			return array_keys($this->columns);
		}
		
		function downloadLicense()
		{
			$app = new App($this->app_id);
			if($app->id = "") return false;
			header("Cache-Control: public");
			header("Cache-Control: no-store, no-cache, must-revalidate");
			header("Cache-Control: post-check=0, pre-check=0", false);
			header("Pragma: no-cache");
			header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
			header("Content-Type: application/octet-stream");
			header("Content-Length: " . strlen($this->license));
			header("Content-Disposition: attachment; filename=" . $this->licenseFilename());
			header("Content-Transfer-Encoding: binary");
			echo $this->license;
			exit;
		}
	}